home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmcd-1.4 / libdi.d / os_odt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-10  |  6.1 KB  |  279 lines

  1. /*
  2.  *   libdi - CD Audio Player Device Interface Library
  3.  *
  4.  *   Copyright (C) 1995  Ti Kan
  5.  *   E-mail: ti@amb.org
  6.  *
  7.  *   This program is free software; you can redistribute it and/or modify
  8.  *   it under the terms of the GNU General Public License as published by
  9.  *   the Free Software Foundation; either version 2 of the License, or
  10.  *   (at your option) any later version.
  11.  *
  12.  *   This program is distributed in the hope that it will be useful,
  13.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *   GNU General Public License for more details.
  16.  *
  17.  *   You should have received a copy of the GNU General Public License
  18.  *   along with this program; if not, write to the Free Software
  19.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *   This software module contains code that interfaces the CD player
  22.  *   application to the SCO Open Desktop operating system.  The name
  23.  *   "SCO" and "ODT" are used here for identification purposes only.
  24.  *   This software and its author are not affiliated with The Santa Cruz
  25.  *   Operation, Inc.
  26.  */
  27. #ifndef LINT
  28. static char *_os_odt_c_ident_ = "@(#)os_odt.c    5.6 94/12/28";
  29. #endif
  30.  
  31. #include "common.d/appenv.h"
  32. #include "common.d/util.h"
  33. #include "libdi.d/libdi.h"
  34. #include "libdi.d/scsipt.h"
  35.  
  36. #if defined(sco) && defined(DI_SCSIPT) && !defined(DEMO_ONLY)
  37.  
  38. extern appdata_t    app_data;
  39. extern bool_t        scsipt_notrom_error;
  40. extern FILE        *errfp;
  41.  
  42. STATIC int        pthru_fd = -1;    /* Passthrough device file desc */
  43. STATIC req_sense_data_t    sense_data;    /* Request sense data buffer */
  44.  
  45.  
  46. /*
  47.  * pthru_send
  48.  *    Build SCSI CDB and send command to the device.
  49.  *
  50.  * Args:
  51.  *    opcode - SCSI command opcode
  52.  *    addr - The "address" portion of the SCSI CDB
  53.  *    buf - Pointer to data buffer
  54.  *    size - Number of bytes to transfer
  55.  *    rsvd - The "reserved" portion of the SCSI CDB
  56.  *    length - The "length" portion of the SCSI CDB
  57.  *    param - The "param" portion of the SCSI CDB
  58.  *    control - The "control" portion of the SCSI CDB
  59.  *    rw - Data transfer direction flag (READ_OP or WRITE_OP)
  60.  *    prnerr - Whether an error message should be displayed
  61.  *         when a command fails
  62.  *
  63.  * Return:
  64.  *    TRUE - command completed successfully
  65.  *    FALSE - command failed
  66.  */
  67. bool_t
  68. pthru_send(
  69.     byte_t        opcode,
  70.     word32_t    addr,
  71.     byte_t        *buf,
  72.     word32_t    size,
  73.     byte_t        rsvd,
  74.     word32_t    length,
  75.     byte_t        param,
  76.     byte_t        control,
  77.     byte_t        rw,
  78.     bool_t        prnerr
  79. )
  80. {
  81.     struct scsicmd    sc;
  82.     union scsi_cdb    *cdb;
  83.  
  84.     
  85.     if (pthru_fd < 0 || scsipt_notrom_error)
  86.         return FALSE;
  87.  
  88.     memset(&sense_data, 0, sizeof(sense_data));
  89.     memset(&sc, 0, sizeof(sc));
  90.     cdb = (union scsi_cdb *) sc.cdb;
  91.  
  92.     /* set up SCSI CDB */
  93.     switch (opcode & 0xf0) {
  94.     case 0xa0:
  95.     case 0xe0:
  96.         /* 12-byte commands */
  97.         cdb->twelve.opcode = opcode;
  98.         cdb->twelve.misc = param;
  99.         cdb->twelve.lun = 0;
  100.         CDB12_BLK(&cdb->twelve, bswap32(addr));
  101.         CDB12_LEN(&cdb->twelve, bswap32(length));
  102.         CDB12_RSV(&cdb->twelve, rsvd);
  103.         CDB12_CTL(&cdb->twelve, control);
  104.  
  105.         sc.cdb_len = 12;
  106.         break;
  107.  
  108.     case 0xc0:
  109.     case 0xd0:
  110.     case 0x20:
  111.     case 0x30:
  112.     case 0x40:
  113.         /* 10-byte commands */
  114.         cdb->ten.opcode = opcode;
  115.         cdb->ten.misc = param;
  116.         cdb->ten.lun = 0;
  117.         CDB10_BLK(&cdb->ten, bswap32(addr));
  118.         CDB10_LEN(&cdb->ten, bswap16((word16_t) length));
  119.         CDB10_RSV(&cdb->ten, rsvd);
  120.         CDB10_CTL(&cdb->ten, control);
  121.  
  122.         sc.cdb_len = 10;
  123.         break;
  124.  
  125.     case 0x00:
  126.     case 0x10:
  127.         /* 6-byte commands */
  128.         cdb->six.opcode = opcode;
  129.         cdb->six.misc = param;
  130.         cdb->six.lun = 0;
  131.         CDB6_BLK(&cdb->six, bswap16((word16_t) addr));
  132.         CDB6_LEN(&cdb->six, (byte_t) length);
  133.         CDB6_CTL(&cdb->six, control);
  134.  
  135.         sc.cdb_len = 6;
  136.         break;
  137.  
  138.     default:
  139.         if (app_data.scsierr_msg && prnerr)
  140.             fprintf(errfp, "0x%02x: Unknown SCSI opcode\n",
  141.                 opcode);
  142.         return FALSE;
  143.     }
  144.  
  145.     DBGDUMP("SCSI CDB bytes", (byte_t *) sc.cdb, sc.cdb_len);
  146.  
  147.     /* set up scsicmd */
  148.     sc.data_ptr = (faddr_t) buf;
  149.     sc.data_len = size;
  150.     sc.is_write = (rw == WRITE_OP);
  151.  
  152.     /* Send the command down via the "pass-through" interface */
  153.     if (ioctl(pthru_fd, SCSIUSERCMD, &sc) < 0) {
  154.         if (app_data.scsierr_msg && prnerr)
  155.             perror("SCSIUSERCMD ioctl failed");
  156.         return FALSE;
  157.     }
  158.  
  159.     if (sc.host_sts || sc.target_sts) {
  160.         if (app_data.scsierr_msg && prnerr) {
  161.             fprintf(errfp,
  162.                 "CD audio: %s %s:\n%s=0x%x %s=0x%x %s=0x%x",
  163.                 "SCSI command fault on",
  164.                 app_data.device,
  165.                 "Opcode",
  166.                 opcode,
  167.                 "Host_status",
  168.                 sc.host_sts,
  169.                 "Target_status",
  170.                 sc.target_sts);
  171.         }
  172.  
  173.         /* Send Request Sense command */
  174.         cdb->six.opcode = OP_S_RSENSE;
  175.         cdb->six.misc = 0;
  176.         cdb->six.lun = 0;
  177.         CDB6_BLK(&cdb->six, 0);
  178.         CDB6_LEN(&cdb->six, SZ_RSENSE);
  179.         CDB6_CTL(&cdb->six, 0);
  180.         sc.data_ptr = (faddr_t) &sense_data;
  181.         sc.data_len = SZ_RSENSE;
  182.         sc.is_write = FALSE;
  183.         sc.cdb_len = 6;
  184.  
  185.         if (ioctl(pthru_fd, SCSIUSERCMD, &sc) < 0 ||
  186.             sense_data.valid == 0) {
  187.             if (app_data.scsierr_msg && prnerr)
  188.                 fprintf(errfp, "\n");
  189.         }
  190.         else if (app_data.scsierr_msg && prnerr) {
  191.             fprintf(errfp, " Key=0x%x Code=0x%x Qual=0x%x\n",
  192.                 sense_data.key,
  193.                 sense_data.code,
  194.                 sense_data.qual);
  195.         }
  196.  
  197.         return FALSE;
  198.     }
  199.     return TRUE;
  200. }
  201.  
  202.  
  203. /*
  204.  * pthru_open
  205.  *    Open SCSI pass-through device
  206.  *
  207.  * Args:
  208.  *    path - device path name string
  209.  *
  210.  * Return:
  211.  *    TRUE - open successful
  212.  *    FALSE - open failed
  213.  */
  214. bool_t
  215. pthru_open(char *path)
  216. {
  217.     struct stat    stbuf;
  218.     char        errstr[ERR_BUF_SZ];
  219.  
  220.     /* Check for validity of device node */
  221.     if (stat(path, &stbuf) < 0) {
  222.         sprintf(errstr, app_data.str_staterr, path);
  223.         cd_fatal_popup(app_data.str_fatal, errstr);
  224.         return FALSE;
  225.     }
  226.     if (!S_ISCHR(stbuf.st_mode)) {
  227.         sprintf(errstr, app_data.str_noderr, path);
  228.         cd_fatal_popup(app_data.str_fatal, errstr);
  229.         return FALSE;
  230.     }
  231.  
  232.     if ((pthru_fd = open(path, O_RDONLY)) < 0) {
  233.         DBGPRN(errfp, "Cannot open %s: errno=%d\n", path, errno);
  234.         return FALSE;
  235.     }
  236.  
  237.     return TRUE;
  238. }
  239.  
  240.  
  241. /*
  242.  * pthru_close
  243.  *    Close SCSI pass-through device
  244.  *
  245.  * Args:
  246.  *    Nothing.
  247.  *
  248.  * Return:
  249.  *    Nothing.
  250.  */
  251. void
  252. pthru_close(void)
  253. {
  254.     if (pthru_fd >= 0) {
  255.         close(pthru_fd);
  256.         pthru_fd = -1;
  257.     }
  258. }
  259.  
  260.  
  261. /*
  262.  * pthru_vers
  263.  *    Return OS Interface Module version string
  264.  *
  265.  * Args:
  266.  *    Nothing.
  267.  *
  268.  * Return:
  269.  *    Module version text string.
  270.  */
  271. char *
  272. pthru_vers(void)
  273. {
  274.     return ("OS Interface module (for SCO ODT)\n");
  275. }
  276.  
  277. #endif    /* sco DI_SCSIPT DEMO_ONLY */
  278.  
  279.